package cool.xinya.ess.security;

import com.alibaba.fastjson.JSON;
import cool.xinya.ess.common.Result;
import cool.xinya.ess.common.ResultEnum;
import cool.xinya.ess.util.ResultUtil;
import org.apache.shiro.subject.Subject;
import org.apache.shiro.web.filter.authz.AuthorizationFilter;
import org.apache.shiro.web.util.WebUtils;
import org.springframework.data.redis.core.SetOperations;
import org.springframework.data.redis.core.StringRedisTemplate;
import org.springframework.util.CollectionUtils;

import javax.servlet.ServletRequest;
import javax.servlet.ServletResponse;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.util.Set;

/**
 * 登录认证,权限验证
 *
 * @author wangxiaolong
 * @date 2019/6/17.
 */
public class CustomRolesAuthorizationFilter extends AuthorizationFilter {
    private final SetOperations<String, String> setOperations;

    public CustomRolesAuthorizationFilter(StringRedisTemplate redisTemplate) {
        setOperations = redisTemplate.opsForSet();
    }

    /**
     * 权限验证
     */
    @Override
    protected boolean isAccessAllowed(ServletRequest request, ServletResponse response, Object mappedValue) {
        Subject subject = getSubject(request, response);
        if (subject.getPrincipal() == null) {
            return false;
        }
        HttpServletRequest req = (HttpServletRequest) request;
        String uri = req.getRequestURI().replace(req.getContextPath(), "");
        // 加载权限对应角色
        Set<String> roles = setOperations.members("security:permission:" + uri);
        // 没有角色限制，有权限访问
        if (CollectionUtils.isEmpty(roles)) {
            return true;
        }
        for (String role : roles) {
            // 用户拥有该角色,有权限访问
            if (subject.hasRole(role)) {
                return true;
            }
        }

        return false;
    }

    /**
     * 验证失败时封装返回信息
     */
    @Override
    protected boolean onAccessDenied(ServletRequest request, ServletResponse response) throws IOException {
        Subject subject = getSubject(request, response);
        Result result;
        if (subject.getPrincipal() == null) {
            result = ResultUtil.error(ResultEnum.LOGIN_ERROR.getCode(), ResultEnum.LOGIN_ERROR.getMsg());
        } else {
            result = ResultUtil.error(ResultEnum.JURISDICTION_ERROR.getCode(), ResultEnum.JURISDICTION_ERROR.getMsg());
        }
        // 封装响应信息
        HttpServletResponse httpServletResponse = WebUtils.toHttp(response);
        httpServletResponse.setCharacterEncoding("UTF-8");
        httpServletResponse.setContentType("application/json");
        httpServletResponse.getWriter().write(JSON.toJSONString(result));
        return false;
    }
}